package com.powerbosframework.beans;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import org.jdom.Document;
import org.jdom.Element;

import com.powerbosframework.beans.BeanObjectFactory;
import com.powerbosframework.beans.access.BeanFactory;
import com.powerbosframework.beans.access.Setter;
import com.powerbosframework.beans.entity.BeanEntity;
import com.powerbosframework.beans.entity.PropertyEntity;
import com.powerbosframework.beans.entity.ViewEntity;
import com.powerbosframework.context.ApplicatioinContextException;
import com.powerbosframework.context.resource.Resource;
import com.powerbosframework.context.resource.ResourceImpl;
import com.powerbosframework.log.LogFactory;
import com.powerbosframework.log.Logger;
import com.powerbosframework.util.ClassLoaderUtil;
import com.powerbosframework.util.StringUtil;
import com.powerbosframework.util.XMLUtil;

/**
 * POJO对象加载器
 * 
 * @author youfu.wang
 * @version 1.0
 */
public class BeanObjectLoader {
	private BeanObjectFactory beanObjectFactory;
	private ClassLoaderUtil beanClassLoader = new ClassLoaderUtil();
	private static Logger log = LogFactory.getInstance();
	private XMLUtil xmlUtil = new XMLUtil();

	public BeanObjectLoader(BeanObjectFactory beanObjectFactory) {
		this.beanObjectFactory = beanObjectFactory;
	}

	/**
	 * 加载POJO实体对象
	 * 
	 * @param location
	 * @throws IOException
	 * @throws ApplicatioinContextException
	 */
	public void loadBeanEntity(String location) throws IOException,
			ApplicatioinContextException {		
		Resource resource = new ResourceImpl(location);			
		this.loadBeanEntity(resource);
	}

	/**
	 * 加载POJO实体对象
	 * 
	 * @param resource
	 * @throws IOException
	 * @throws ApplicatioinContextException
	 */
	public void loadBeanEntity(Resource resource) throws IOException,
			ApplicatioinContextException {
		InputStream stream = resource.getInputStream();
		if (stream == null)
			throw new IOException(resource + "资源文件没有找到");

		Document doc = xmlUtil.parse(stream);
		if (doc == null)
			throw new ApplicatioinContextException(resource + "资源文件解析失败");
		Element rootE = doc.getRootElement();
		if (rootE == null)
			throw new ApplicatioinContextException(resource + "资源文件解析失败");
		List beans = rootE.getChildren("bean");
		if (beans == null)
			return;
		for (int i = 0; i < beans.size(); i++) {
			Element beanE = (Element) beans.get(i);
			this.loadBeanEntity(beanE);
		}
		// 加载全局视图
		this.loadGlobalViews(rootE.getChild("views"));
	}

	/**
	 * 加载POJO实体对象
	 * 
	 * @param beanE
	 */
	private void loadBeanEntity(Element beanE) {
		String id = StringUtil.replaceNull(beanE.getAttributeValue("id"));
		String clazz = StringUtil.replaceNull(beanE.getAttributeValue("class"));
		String method = StringUtil.replaceNull(beanE
				.getAttributeValue("method"));
		String singleton = StringUtil.replaceNull(beanE
				.getAttributeValue("singleton"));
		if ("".equals(clazz))
			return;
		if ("".equals(singleton))
			singleton = "true";
		BeanEntity beanEntity = new BeanEntity();
		beanEntity.setId(id);
		beanEntity.setClazz(clazz);
		beanEntity.setMethod(method);
		beanEntity.setSingleton(singleton);

		// 加载属性配置
		this.loadBeanProperties(beanEntity, beanE);
		// 加载视图配置
		this.loadBeanViews(beanEntity, beanE);
		beanObjectFactory.setBeanEntity(beanEntity.getId(), beanEntity);
		// 加载POJO实例
		if ("true".equals(singleton)) {		
			Object obj=this.newBeanInstance(beanEntity);
			beanObjectFactory.setBean(beanEntity.getId(), obj);
		}
	}

	private void loadGlobalViews(Element viewsE) {
		if (viewsE == null)
			return;
		List views = viewsE.getChildren("view");
		if (views == null)
			return;
		for (int i = 0; i < views.size(); i++) {
			Element viewE = (Element) views.get(i);
			String name = StringUtil.replaceNull(viewE
					.getAttributeValue("name"));
			String value = StringUtil.replaceNull(viewE
					.getAttributeValue("value"));
			ViewEntity viewEntity = new ViewEntity();
			viewEntity.setName(name);
			viewEntity.setValue(value);
			beanObjectFactory.setGlobalViews(name, viewEntity);
		}
	}

	/**
	 * 加载视图配置
	 * 
	 * @param beanEntity
	 * @param beanE
	 */
	private void loadBeanViews(BeanEntity beanEntity, Element beanE) {
		if (beanE == null)
			return;
		Element viewE = beanE.getChild("view");
		if (viewE == null)
			return;
		String name = StringUtil.replaceNull(viewE.getAttributeValue("name"));
		String value = StringUtil.replaceNull(viewE.getAttributeValue("value"));
		ViewEntity viewEntity = new ViewEntity();
		viewEntity.setName(name);
		viewEntity.setValue(value);
		beanEntity.setViewEntity(viewEntity);
	}

	/**
	 * 加载属性配置
	 * 
	 * @param obj
	 * @param beanE
	 */
	private void loadBeanProperties(BeanEntity beanEntity, Element beanE) {
		if (beanE == null)
			return;
		List properties = beanE.getChildren("property");
		if (properties == null)
			return;
		List beanEntityProperties = new ArrayList();
		for (int i = 0; i < properties.size(); i++) {
			Element proE = (Element) properties.get(i);
			String name = StringUtil
					.replaceNull(proE.getAttributeValue("name"));
			String value = StringUtil.replaceNull(proE
					.getAttributeValue("value"));
			String ref = StringUtil.replaceNull(proE.getAttributeValue("ref"));
			PropertyEntity proEntity = new PropertyEntity();
			proEntity.setName(name);
			proEntity.setValue(value);
			proEntity.setRef(ref);
			beanEntityProperties.add(proEntity);
		}
		beanEntity.setProperties(beanEntityProperties);
	}

	/**
	 * 加载属性配置值
	 * 
	 * @throws ClassNotFoundException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public void loadBeanPropertyValues() {
		for (Map.Entry<String, BeanEntity> entry : beanObjectFactory
				.getBeanEntities().entrySet()) {
			String key = entry.getKey();
			BeanEntity beanEntity = entry.getValue();
			this.loadBeanPropertyValues(beanEntity);
		}
	}
	public void loadBeanPropertyValues(BeanEntity beanEntity){		
		Object obj=null;
		if ("true".equals(beanEntity.getSingleton())) {	
			obj = beanObjectFactory.getBean(beanEntity.getId());	
			this.loadBeanPropertyValues(beanEntity,obj);	
		}
		
	}
	public void loadBeanPropertyValues(BeanEntity beanEntity,Object obj){	
		List properties = beanEntity.getProperties();
		if (properties == null)
			return;
		for (int i = 0; i < properties.size(); i++) {
			PropertyEntity proEntity = (PropertyEntity) properties
					.get(i);
			Setter setter = BeanFactory.getSetter(obj.getClass(),
					proEntity.getName());
			if (!"".equals(proEntity.getRef())) {
				setter.set(obj, beanObjectFactory.getBean(proEntity
						.getRef()));
			} else {
				setter.set(obj, proEntity.getValue());
			}
		}
	}
	public Object newBeanInstance(BeanEntity beanEntity){
		Object obj=null;
		// 实例化POJO对象
		try {			
			 obj= beanClassLoader.loadClass(beanEntity.getClazz())
				.newInstance();											
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return obj;
	}
	
}
